import axios from "axios";

const promiseState = promise => {
    const target = {}
    //  target 是已完成的状态   Promise.race 优先判断第一个参数的状态，第一个如果是已完成就会有结果返回
    return Promise.race([promise, target]).then(value => value === target ? 'pending' : 'fu').catch(err => 'rejected')
}

export default class ConcurrentQueue {
    constructor({ maxConcurrentCount, callback }) {
        this.maxConcurrentCount = maxConcurrentCount; //最大并发数
        this.callback = callback;//相关回调方法
        this.taskQueue = [];
        this.responses = {};
        this.completeCount = 0
        this.stopTask = false
        this.currentQueue = []

    }
    startQueue() {
        this._doRequest()
    }
    cancel() {
        
        this.stopTask = true
        //正常情况下 最多有 maxConcurrentCount  但是保险起见  _getMaxCount
        // for (let i = 0; i < this.currentQueue.length; i++) {
        //     let task = this.currentQueue[i]
        //     if (task.params.cancelToken) {
        //         promiseState(task.params.cancelToken.token.promise).then(state => {
        //             if (state === 'pending') {
        //                 task.params.cancelToken.cancel('取消请求')
        //             }
        //         })
        //     }
        // }
        // this.endQueue()

    }
    endQueue() {
        this.taskQueue = [];
    }
    addTask(task) {

        this.taskQueue.push(task);
    }

    _doRequest() {
        if (this.stopTask) {
            
            if(this.callback){
                
                this.callback.cancelback&&this.callback.cancelback(this.taskQueue.length)
            }
            return
        }
        if (!this.taskQueue.length) return;
        const minConcurrentCount = this._getMinCount(
            this.maxConcurrentCount,
            this.taskQueue.length
        )

        for (let i = 0; i < minConcurrentCount; i++) {
            const task = this.taskQueue.shift();
            this.currentQueue.push(task)
            this.maxConcurrentCount--;
            this._runTask(task);
        }

    }

    _runTask(task) {
       

        
        task.params = { runing: true, cancelToken: axios.CancelToken.source(), ...task.params }

        task.fn(task.params).then(res => {
                this.responses[task.name] = {
                result: res,
                error: null,
            };
        }).catch(err => {
            if (axios.isCancel(err)) {
                this.responses[task.name] = {
                    result: null,
                    error: '取消上传',
                };
            } else {
                this.responses[task.name] = {
                    result: null,
                    error: err,
                };
            }

        }).finally(() => {            
            this.currentQueue = this.currentQueue.filter(taskItem=>taskItem.name!==task.name)
            this.maxConcurrentCount++;
            this._doRequest();
            if (this.callback) {
                
                this.callback.complete && this.callback.complete(this.responses);
            }
        });
    }

    _getMaxCount(count1, count2) {
        return Math.max(count1, count2);
    }

    _getMinCount(count1, count2) {
        return Math.min(count1, count2);
    }
}